using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using com.youzu.warh.protocol;
using LitJson;
using UnityEditor;
using UnityEngine;
using Yoozoo.Gameplay.Liberty.AI;
using Yoozoo.Gameplay.Liberty.Tools.Editor;

public class ProtobufConfigConvert
{
    [MenuItem("GTATools/Json配置转Protobuf", isValidateFunction:false)]
    static void OpenEditor()
    {
        if (EditorApplication.isCompiling || EditorUtility.scriptCompilationFailed)
        {
            EditorUtility.DisplayDialog("Error", "Compile Error", "Ok");
            return;
        }

        // lod0_npc
        convertConfig<PbNpcDataConfig>(Application.dataPath + "/Arts/Config/LibertyConfig/lod0_npc.json", (pbArray) =>
        {
            PbNpcDataConfigs configs = new PbNpcDataConfigs();
            configs.Data.AddRange(pbArray);
            saveProtoBuf(Application.dataPath + "/BinaryAssets/LibertyConfig/lod0_npc.bytes", configs);
        });
        // rpg_npc
        convertConfig<PbAIPropertyDataConfig>(Application.dataPath + "/Arts/Config/LibertyConfig/rpg_npc.json", (pbArray) =>
        {
            PbAIPropertyDataConfigs configs = new PbAIPropertyDataConfigs();
            configs.Data.AddRange(pbArray);
            saveProtoBuf(Application.dataPath + "/BinaryAssets/LibertyConfig/rpg_npc.bytes", configs);
        });
        // GTA_skill
        convertConfig<PbBoxingDataConfig>(Application.dataPath + "/Arts/Config/LibertyConfig/GTA_skill.json", (pbArray) =>
        {
            PbBoxingDataConfigs configs = new PbBoxingDataConfigs();
            configs.Data.AddRange(pbArray);
            saveProtoBuf(Application.dataPath + "/BinaryAssets/LibertyConfig/GTA_skill.bytes", configs);
        });
        // GTA_weapon
        convertConfig<PbWeaponDataConfig>(Application.dataPath + "/Arts/Config/LibertyConfig/GTA_weapon.json", (pbArray) =>
        {
            PbWeaponDataConfigs configs = new PbWeaponDataConfigs();
            configs.Data.AddRange(pbArray);
            saveProtoBuf(Application.dataPath + "/BinaryAssets/LibertyConfig/GTA_weapon.bytes", configs);
        });
        // GTA_equip_model
        convertConfig<PbEquipModelDataConfig>(Application.dataPath + "/Arts/Config/LibertyConfig/GTA_equip_model.json", (pbArray) =>
        {
            PbEquipModelDataConfigs configs = new PbEquipModelDataConfigs();
            configs.Data.AddRange(pbArray);
            saveProtoBuf(Application.dataPath + "/BinaryAssets/LibertyConfig/GTA_equip_model.bytes", configs);
        });
        // GTA_weapon_bullet
        convertConfig<PbWeaponBulletDataConfig>(Application.dataPath + "/Arts/Config/LibertyConfig/GTA_weapon_bullet.json", (pbArray) =>
        {
            PbWeaponBulletDataConfigs configs = new PbWeaponBulletDataConfigs();
            configs.Data.AddRange(pbArray);
            saveProtoBuf(Application.dataPath + "/BinaryAssets/LibertyConfig/GTA_weapon_bullet.bytes", configs);
        });
        // GTA_weapon_element
        convertConfig<PbWeaponElementDataConfig>(Application.dataPath + "/Arts/Config/LibertyConfig/GTA_weapon_element.json", (pbArray) =>
        {
            PbWeaponElementDataConfigs configs = new PbWeaponElementDataConfigs();
            configs.Data.AddRange(pbArray);
            saveProtoBuf(Application.dataPath + "/BinaryAssets/LibertyConfig/GTA_weapon_element.bytes", configs);
        });
        // GTA_weapon_interact
        convertConfig<PbWeaponInteractDataConfig>(Application.dataPath + "/Arts/Config/LibertyConfig/GTA_weapon_interact.json", (pbArray) =>
        {
            PbWeaponInteractDataConfigs configs = new PbWeaponInteractDataConfigs();
            configs.Data.AddRange(pbArray);
            saveProtoBuf(Application.dataPath + "/BinaryAssets/LibertyConfig/GTA_weapon_interact.bytes", configs);
        });
        // GTA_item
        convertConfig<PbItemConfig>(Application.dataPath + "/Arts/Config/LibertyConfig/GTA_item.json", (pbArray) =>
        {
            PbItemConfigs configs = new PbItemConfigs();
            configs.Data.AddRange(pbArray);
            saveProtoBuf(Application.dataPath + "/BinaryAssets/LibertyConfig/GTA_item.bytes", configs);
        });
        EditorUtility.DisplayDialog("", "配置转换完成 ^_^", "ok");
    }

    static void saveProtoBuf<T>(string fullpath, T data)
    {
        using (MemoryStream memoryStream = new MemoryStream())
        {
            ProtoBuf.Serializer.Serialize(memoryStream, data);
            using (FileStream file = new FileStream(fullpath, FileMode.Create, FileAccess.Write))
            {
                memoryStream.WriteTo(file);
            }
        }
    }
    
    static void convertConfig<T>(string path, Action<T[]> callback) where T : class, new()
    {
        string jsonStr = File.ReadAllText(path);
        if (!string.IsNullOrEmpty(jsonStr))
        {
            JsonData datas = JsonMapper.ToObject(jsonStr);
            Type type2 = typeof(T);
            PropertyInfo[] properties = type2.GetProperties(BindingFlags.Instance | BindingFlags.Public);
            
            int i = 0;
            T[] pbArray = new T[datas.Count];
            foreach (JsonData data in datas)
            {
                T pbElement = new T();
                foreach (var pbPropertyInfo in properties)
                {
                    // UnityEngine.Debug.LogError($"propertyName: {pbPropertyInfo.Name}");
                    var value = data[pbPropertyInfo.Name];
                    Debug.Log($"{pbPropertyInfo.Name} {value}");
                    // UnityEngine.Debug.LogError($"JsonData value: {value}, jsonType: {value.GetJsonType()}");
                    switch (value.GetJsonType())
                    {
                        case JsonType.Array:
                            {
                                if (value.Count > 0)
                                {
                                    if(pbPropertyInfo.PropertyType == typeof(List<bool>))
                                    {
                                        List<bool> array = pbPropertyInfo.GetValue(pbElement) as List<bool>;
                                        for(int j=0; j<value.Count; ++j)
                                        {
                                            array.Add((bool)value[j]);
                                        }
                                    }
                                    else if (pbPropertyInfo.PropertyType == typeof(List<float>))
                                    {
                                        List<float> array = pbPropertyInfo.GetValue(pbElement) as List<float>;
                                        for(int j=0; j<value.Count; ++j)
                                        {
                                            if (value[j].IsInt)
                                            {
                                                array.Add((int)value[j]);
                                            }
                                            else if (value[j].IsDouble)
                                            {
                                                array.Add((float)(double)value[j]);
                                            }
                                        }
                                    }
                                    else if (pbPropertyInfo.PropertyType == typeof(List<double>))
                                    {
                                        List<double> array = pbPropertyInfo.GetValue(pbElement) as List<double>;
                                        for(int j=0; j<value.Count; ++j)
                                        {
                                            if (value[j].IsInt)
                                            {
                                                array.Add((int)value[j]);
                                            }
                                            else if (value[j].IsDouble)
                                            {
                                                array.Add((double)value[j]);
                                            }
                                        }
                                    }
                                    else if (pbPropertyInfo.PropertyType == typeof(List<int>))
                                    {
                                        List<int> array = pbPropertyInfo.GetValue(pbElement) as List<int>;
                                        for(int j=0; j<value.Count; ++j)
                                        {
                                            array.Add((int)value[j]);
                                        }
                                    }
                                    else if (pbPropertyInfo.PropertyType == typeof(List<long>))
                                    {
                                        List<long> array = pbPropertyInfo.GetValue(pbElement) as List<long>;
                                        for(int j=0; j<value.Count; ++j)
                                        {
                                            array.Add((long)value[j]);
                                        }
                                    }
                                    else if (pbPropertyInfo.PropertyType == typeof(List<string>))
                                    {
                                        List<string> array = pbPropertyInfo.GetValue(pbElement) as List<string>;
                                        for(int j=0; j<value.Count; ++j)
                                        {
                                            array.Add((string)value[j]);
                                        }
                                    }
                                }
                            }
                            break;
                        case JsonType.Boolean:
                            {
                                pbPropertyInfo.SetValue(pbElement, (bool)value);
                            }
                            break;
                        case JsonType.Double:
                            {
                                if (pbPropertyInfo.PropertyType == typeof(System.Single))
                                {
                                    pbPropertyInfo.SetValue(pbElement, (float)(double)value);
                                }
                                else
                                {
                                    pbPropertyInfo.SetValue(pbElement, (double)value);
                                }
                            }
                            break;
                        case JsonType.Int:
                        case JsonType.Long:
                            {
                                if (pbPropertyInfo.PropertyType == typeof(System.Int32))
                                {
                                    pbPropertyInfo.SetValue(pbElement, (int)value);
                                }
                                else
                                {
                                    pbPropertyInfo.SetValue(pbElement, (long)value);
                                }
                            }
                            break;
                        case JsonType.String:
                            {
                                pbPropertyInfo.SetValue(pbElement, (string)value);
                            }
                            break;

                        default:
                            {
                                UnityEngine.Debug.LogError($"不支持转换的类型: {value.GetJsonType()}");
                            }
                            break;
                    }
                }

                pbArray[i] = pbElement;
                i++;
            }
            
            callback?.Invoke(pbArray);
        }
    }

    
}
